Disabled external gits

This commit is contained in:
2022-04-07 18:54:11 +02:00
parent 15e7120d6d
commit 0fb3e365d4
376 changed files with 50840 additions and 0 deletions

View File

@ -0,0 +1,6 @@
#include <stdlib.h>
int main(void) {
/* TODO : complete this function with your application */
return EXIT_SUCCESS;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -0,0 +1,84 @@
/**
* @author Philemon Favrod
* @brief Example of ping-pong buffering using the framebuffer.
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <assert.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <unistd.h>
struct fb_fix_screeninfo fix_info;
struct fb_var_screeninfo var_info;
uint32_t *frame_buffer;
int num_buffers;
int num_pixels_per_buffer;
int fb_fd;
inline uint32_t make_color(uint8_t red, uint8_t green, uint8_t blue)
{
uint32_t r = red << var_info.red.offset;
uint32_t g = green << var_info.green.offset;
uint32_t b = blue << var_info.blue.offset;
return r | g | b;
}
int main(void)
{
fb_fd = open("/dev/fb0", O_RDWR);
assert(fb_fd >= 0);
// Get screen information
int ret = ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix_info);
assert(ret >= 0);
ret = ioctl(fb_fd, FBIOGET_VSCREENINFO, &var_info);
assert(ret >= 0);
// Map the frame buffer in user memory
frame_buffer = mmap(NULL, var_info.yres_virtual * fix_info.line_length, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
assert(frame_buffer != MAP_FAILED);
// Reminder: with prsoc_fbdev driver the number of buffer can be changed in the device tree
num_buffers = (var_info.yres_virtual * var_info.xres_virtual) / (var_info.xres * var_info.yres);
num_pixels_per_buffer = var_info.yres * var_info.xres;
int buffer_idx;
for (buffer_idx = 0; buffer_idx < num_buffers; ++buffer_idx) {
// Compute the color of the buffer
// Buffers 0, 3, 6, ... will be red
// Buffers 1, 4, 7, ... will be green
// Buffers 2, 5, 8, ... will be blue
uint32_t color = make_color(0xff, 0, 0);
if (buffer_idx % 3 == 1) {
color = make_color(0, 0xff, 0);
} else if (buffer_idx % 3 == 2) {
color = make_color(0, 0, 0xff);
}
int pixel_idx;
for (pixel_idx = buffer_idx * num_pixels_per_buffer; pixel_idx < (buffer_idx + 1) * num_pixels_per_buffer; ++pixel_idx) {
frame_buffer[pixel_idx] = color;
}
}
while (1) {
int i;
for (i = 0; i < num_buffers; ++i) {
var_info.yoffset = i * var_info.yres;
ret = ioctl(fb_fd, FBIOPAN_DISPLAY, &var_info);
assert(ret >= 0);
usleep(3000000);
}
}
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,24 @@
#ifndef __IORW_H__
#define __IORW_H__
#ifdef __nios2_arch__
#include <io.h>
#define io_write_8(base, ofst, data) (IOWR_8DIRECT((base), (ofst), (data)))
#define io_write_16(base, ofst, data) (IOWR_16DIRECT((base), (ofst), (data)))
#define io_write_32(base, ofst, data) (IOWR_32DIRECT((base), (ofst), (data)))
#define io_read_8(base, ofst) (IORD_8DIRECT((base), (ofst)))
#define io_read_16(base, ofst) (IORD_16DIRECT((base), (ofst)))
#define io_read_32(base, ofst) (IORD_32DIRECT((base), (ofst)))
#else
#include <socal/socal.h>
#define io_write_8(base, ofst, data) (alt_write_byte((uintptr_t) (base) + (ofst), (data)))
#define io_write_16(base, ofst, data) (alt_write_hword((uintptr_t) (base) + (ofst), (data)))
#define io_write_32(base, ofst, data) (alt_write_word((uintptr_t) (base) + (ofst), (data)))
#define io_read_8(base, ofst) (alt_read_byte((uintptr_t) (base) + (ofst)))
#define io_read_16(base, ofst) (alt_read_hword((uintptr_t) (base) + (ofst)))
#define io_read_32(base, ofst) (alt_read_word((uintptr_t) (base) + (ofst)))
#endif
#endif

View File

@ -0,0 +1,79 @@
#include "joysticks.h"
#define JOYSTICK_RIGHT_VRY_MCP3204_CHANNEL (0)
#define JOYSTICK_RIGHT_VRX_MCP3204_CHANNEL (1)
#define JOYSTICK_LEFT_VRY_MCP3204_CHANNEL (2)
#define JOYSTICK_LEFT_VRX_MCP3204_CHANNEL (3)
/**
* joysticks_inst
*
* Instantiate a joysticks device structure.
*
* @param base Base address of the MCP3204 component connected to the joysticks.
*/
joysticks_dev joysticks_inst(void *mcp3204_base) {
joysticks_dev dev;
dev.mcp3204 = mcp3204_inst((void *) mcp3204_base);
return dev;
}
/**
* joysticks_init
*
* Initializes the joysticks device.
*
* @param dev joysticks device structure.
*/
void joysticks_init(joysticks_dev *dev) {
mcp3204_init(&(dev->mcp3204));
}
/**
* joysticks_read_left_vertical
*
* Returns the vertical position of the left joystick. Return value ranges
* between JOYSTICKS_MIN_VALUE and JOYSTICKS_MAX_VALUE.
*
* @param dev joysticks device structure.
*/
uint32_t joysticks_read_left_vertical(joysticks_dev *dev) {
return JOYSTICKS_MAX_VALUE - mcp3204_read(&dev->mcp3204, JOYSTICK_RIGHT_VRY_MCP3204_CHANNEL);
}
/**
* joysticks_read_left_horizontal
*
* Returns the horizontal position of the left joystick. Return value ranges
* between JOYSTICKS_MIN_VALUE and JOYSTICKS_MAX_VALUE.
*
* @param dev joysticks device structure.
*/
uint32_t joysticks_read_left_horizontal(joysticks_dev *dev) {
return mcp3204_read(&dev->mcp3204, JOYSTICK_LEFT_VRX_MCP3204_CHANNEL);
}
/**
* joysticks_read_right_vertical
*
* Returns the vertical position of the right joystick. Return value ranges
* between JOYSTICKS_MIN_VALUE and JOYSTICKS_MAX_VALUE.
*
* @param dev joysticks device structure.
*/
uint32_t joysticks_read_right_vertical(joysticks_dev *dev) {
return JOYSTICKS_MAX_VALUE - mcp3204_read(&dev->mcp3204, JOYSTICK_RIGHT_VRY_MCP3204_CHANNEL);
}
/**
* joysticks_read_right_horizontal
*
* Returns the horizontal position of the left joystick. Return value ranges
* between JOYSTICKS_MIN_VALUE and JOYSTICKS_MAX_VALUE.
*
* @param dev joysticks device structure.
*/
uint32_t joysticks_read_right_horizontal(joysticks_dev *dev) {
return mcp3204_read(&dev->mcp3204, JOYSTICK_RIGHT_VRX_MCP3204_CHANNEL);
}

View File

@ -0,0 +1,27 @@
#ifndef __JOYSTICKS_H__
#define __JOYSTICKS_H__
#include "mcp3204/mcp3204.h"
/* joysticks device structure */
typedef struct joysticks_dev {
mcp3204_dev mcp3204; /* MCP3204 device handle */
} joysticks_dev;
/*******************************************************************************
* Public API
******************************************************************************/
#define JOYSTICKS_MIN_VALUE (MCP3204_MIN_VALUE)
#define JOYSTICKS_MAX_VALUE (MCP3204_MAX_VALUE)
joysticks_dev joysticks_inst(void *mcp3204_base);
void joysticks_init(joysticks_dev *dev);
uint32_t joysticks_read_left_vertical(joysticks_dev *dev);
uint32_t joysticks_read_left_horizontal(joysticks_dev *dev);
uint32_t joysticks_read_right_vertical(joysticks_dev *dev);
uint32_t joysticks_read_right_horizontal(joysticks_dev *dev);
#endif /* __JOYSTICKS_H__ */

View File

@ -0,0 +1,44 @@
#include "mcp3204.h"
#include "iorw.h"
#define MCP3204_NUM_CHANNELS (4)
/**
* mcp3204_inst
*
* Instantiate a mcp3204 device structure.
*
* @param base Base address of the component.
*/
mcp3204_dev mcp3204_inst(void *base) {
mcp3204_dev dev;
dev.base = base;
return dev;
}
/**
* mcp3204_init
*
* Initializes the mcp3204 device.
*
* @param dev mcp3204 device structure.
*/
void mcp3204_init(mcp3204_dev *dev) {
return;
}
/**
* mcp3204_read
*
* Reads the register corresponding to the supplied channel parameter.
*
* @param dev mcp3204 device structure.
* @param channel channel to be read
*/
uint32_t mcp3204_read(mcp3204_dev *dev, uint32_t channel) {
if (channel >= 4)
return 0;
return io_read_32(dev->base, channel * 4);
}

View File

@ -0,0 +1,23 @@
#ifndef __MCP3204_H__
#define __MCP3204_H__
#include <stdint.h>
/* mcp3204 device structure */
typedef struct mcp3204_dev {
void *base; /* Base address of component */
} mcp3204_dev;
/*******************************************************************************
* Public API
******************************************************************************/
#define MCP3204_MIN_VALUE (0)
#define MCP3204_MAX_VALUE (4095)
mcp3204_dev mcp3204_inst(void *base);
void mcp3204_init(mcp3204_dev *dev);
uint32_t mcp3204_read(mcp3204_dev *dev, uint32_t channel);
#endif /* __MCP3204_H__ */

View File

@ -0,0 +1,9 @@
#ifndef __MCP3204_REGS_H__
#define __MCP3204_REGS_H__
#define MCP3204_CHANNEL_0_OFST (0 * 4) /* RO */
#define MCP3204_CHANNEL_1_OFST (1 * 4) /* RO */
#define MCP3204_CHANNEL_2_OFST (2 * 4) /* RO */
#define MCP3204_CHANNEL_3_OFST (3 * 4) /* RO */
#endif /* __MCP3204_REGS_H__ */

View File

@ -0,0 +1,117 @@
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
#include "lepton_regs.h"
#include "lepton.h"
#include "iorw.h"
/**
* lepton_inst
*
* Instantiate a lepton device structure.
*
* @param base Base address of the component.
*/
lepton_dev lepton_inst(void *base) {
lepton_dev dev;
dev.base = base;
return dev;
}
/**
* lepton_init
*
* Initializes the lepton device.
*
* @param dev lepton device structure.
*/
void lepton_init(lepton_dev *dev) {
return;
}
/**
* lepton_start_capture
*
* Instructs the device to start the frame capture process.
*
* @param dev lepton device structure.
*/
void lepton_start_capture(lepton_dev *dev) {
io_write_16(dev->base, LEPTON_REGS_COMMAND_OFST, 0x1);
}
/**
* lepton_error_check
*
* @abstract Check for errors at the device level.
* @param dev lepton device structure.
* @return true if there was an error, and false otherwise.
*/
bool lepton_error_check(lepton_dev *dev) {
return (io_read_16(dev->base, LEPTON_REGS_STATUS_OFST) & 0x2) != 0;
}
/**
* lepton_wait_until_eof
*
* Waits until the frame being captured has been fully received and saved in the
* internal memory.
*
* @param dev lepton device structure.
*/
void lepton_wait_until_eof(lepton_dev *dev) {
while (io_read_16(dev->base, LEPTON_REGS_STATUS_OFST) & 0x1);
}
/**
* lepton_save_capture
*
* Saves the captured frame on the host filesystem under the supplied filename.
* The frame will be saved in PGM format.
*
* @param dev lepton device structure.
* @param adjusted Setting this parameter to false will cause RAW sensor data to
* be written to the file.
* Setting this parameter to true will cause a preprocessed image
* (with a stretched dynamic range) to be saved to the file.
*
* @param fname the output file name.
*/
void lepton_save_capture(lepton_dev *dev, bool adjusted, FILE* file) {
assert(file);
const uint8_t num_rows = 60;
const uint8_t num_cols = 80;
uint16_t offset = LEPTON_REGS_RAW_BUFFER_OFST;
uint16_t max_value = io_read_16(dev->base, LEPTON_REGS_MAX_OFST);
if (adjusted) {
offset = LEPTON_REGS_ADJUSTED_BUFFER_OFST;
max_value = 0x3fff;
}
/* Write PGM header */
fprintf(file, "P2\n%" PRIu8 " %" PRIu8 "\n%" PRIu16, num_cols, num_rows, max_value);
/* Write body */
uint8_t row = 0;
for (row = 0; row < num_rows; ++row) {
fprintf(file, "\n");
uint8_t col = 0;
for (col = 0; col < num_cols; ++col) {
if (col > 0) {
fprintf(file, " ");
}
uint16_t current_ofst = offset + (row * num_cols + col) * sizeof(uint16_t);
uint16_t pix_value = io_read_16(dev->base, current_ofst);
fprintf(file, "%" PRIu16, pix_value);
}
}
assert(!fclose(file));
}

View File

@ -0,0 +1,23 @@
#ifndef __LEPTON_H__
#define __LEPTON_H__
#include <stdbool.h>
/* lepton device structure */
typedef struct {
void *base; /* Base address of the component */
} lepton_dev;
/*******************************************************************************
* Public API
******************************************************************************/
lepton_dev lepton_inst(void *base);
void lepton_init(lepton_dev *dev);
void lepton_start_capture(lepton_dev *dev);
void lepton_wait_until_eof(lepton_dev *dev);
bool lepton_error_check(lepton_dev *dev);
void lepton_save_capture(lepton_dev *dev, bool adjusted, FILE* file);
#endif /* __LEPTON_H__ */

View File

@ -0,0 +1,25 @@
#ifndef __LEPTON_REGS_H__
#define __LEPTON_REGS_H__
/* Register offsets */
#define LEPTON_REGS_COMMAND_OFST ( 0 * 2) /* WO */
#define LEPTON_REGS_STATUS_OFST ( 1 * 2) /* RO */
#define LEPTON_REGS_MIN_OFST ( 2 * 2) /* RO */
#define LEPTON_REGS_MAX_OFST ( 3 * 2) /* RO */
#define LEPTON_REGS_SUM_LSB_OFST ( 4 * 2) /* RO */
#define LEPTON_REGS_SUM_MSB_OFST ( 5 * 2) /* RO */
#define LEPTON_REGS_ROW_IDX_OFST ( 6 * 2) /* RO */
#define LEPTON_REGS_RAW_BUFFER_OFST ( 8 * 2) /* RO */
#define LEPTON_REGS_ADJUSTED_BUFFER_OFST (8192 * 2) /* RO */
/* Command register */
#define LEPTON_COMMAND_START (0x0001)
/* Status register */
#define LEPTON_STATUS_CAPTURE_IN_PROGRESS_MASK (1 << 0)
#define LEPTON_STATUS_ERROR_MASK (1 << 1)
#define LEPTON_REGS_BUFFER_NUM_PIXELS (80 * 60)
#define LEPTON_REGS_BUFFER_BYTELENGTH (LEPTON_REGS_BUFFER_NUM_PIXELS * 2)
#endif /* __LEPTON_REGS_H__ */

View File

@ -0,0 +1,109 @@
#include "pantilt.h"
/**
* pantilt_inst
*
* Instantiate a pantilt device structure.
*
* @param pwm_v_base Base address of the vertical PWM component.
* @param pwm_h_base Base address of the horizontal PWM component.
*/
pantilt_dev pantilt_inst(void *pwm_v_base, void *pwm_h_base) {
pantilt_dev dev;
dev.pwm_v = pwm_inst(pwm_v_base);
dev.pwm_h = pwm_inst(pwm_h_base);
return dev;
}
/**
* pantilt_init
*
* Initializes the pantilt device.
*
* @param dev pantilt device structure.
*/
void pantilt_init(pantilt_dev *dev) {
pwm_init(&(dev->pwm_v));
pwm_init(&(dev->pwm_h));
}
/**
* pantilt_configure_vertical
*
* Configure the vertical PWM component.
*
* @param dev pantilt device structure.
* @param duty_cycle pwm duty cycle in us.
*/
void pantilt_configure_vertical(pantilt_dev *dev, uint32_t duty_cycle) {
// Need to compensate for inverted servo rotation.
duty_cycle = PANTILT_PWM_V_MAX_DUTY_CYCLE_US - duty_cycle + PANTILT_PWM_V_MIN_DUTY_CYCLE_US;
pwm_configure(&(dev->pwm_v),
duty_cycle,
PANTILT_PWM_PERIOD_US,
PANTILT_PWM_CLOCK_FREQ_HZ);
}
/**
* pantilt_configure_horizontal
*
* Configure the horizontal PWM component.
*
* @param dev pantilt device structure.
* @param duty_cycle pwm duty cycle in us.
*/
void pantilt_configure_horizontal(pantilt_dev *dev, uint32_t duty_cycle) {
// Need to compensate for inverted servo rotation.
duty_cycle = PANTILT_PWM_H_MAX_DUTY_CYCLE_US - duty_cycle + PANTILT_PWM_H_MIN_DUTY_CYCLE_US;
pwm_configure(&(dev->pwm_h),
duty_cycle,
PANTILT_PWM_PERIOD_US,
PANTILT_PWM_CLOCK_FREQ_HZ);
}
/**
* pantilt_start_vertical
*
* Starts the vertical pwm controller.
*
* @param dev pantilt device structure.
*/
void pantilt_start_vertical(pantilt_dev *dev) {
pwm_start(&(dev->pwm_v));
}
/**
* pantilt_start_horizontal
*
* Starts the horizontal pwm controller.
*
* @param dev pantilt device structure.
*/
void pantilt_start_horizontal(pantilt_dev *dev) {
pwm_start(&(dev->pwm_h));
}
/**
* pantilt_stop_vertical
*
* Stops the vertical pwm controller.
*
* @param dev pantilt device structure.
*/
void pantilt_stop_vertical(pantilt_dev *dev) {
pwm_stop(&(dev->pwm_v));
}
/**
* pantilt_stop_horizontal
*
* Stops the horizontal pwm controller.
*
* @param dev pantilt device structure.
*/
void pantilt_stop_horizontal(pantilt_dev *dev) {
pwm_stop(&(dev->pwm_h));
}

View File

@ -0,0 +1,39 @@
#ifndef __PANTILT_H__
#define __PANTILT_H__
#include "pwm/pwm.h"
/* joysticks device structure */
typedef struct pantilt_dev {
pwm_dev pwm_v; /* Vertical PWM device handle */
pwm_dev pwm_h; /* Horizontal PWM device handle */
} pantilt_dev;
/*******************************************************************************
* Public API
******************************************************************************/
#define PANTILT_PWM_CLOCK_FREQ_HZ (50000000) // 50.00 MHz
#define PANTILT_PWM_PERIOD_US (25000) // 25.00 ms
/* Vertical servo */
#define PANTILT_PWM_V_MIN_DUTY_CYCLE_US (950) // 0.95 ms
#define PANTILT_PWM_V_MAX_DUTY_CYCLE_US (2150) // 2.15 ms
/* Horizontal servo */
#define PANTILT_PWM_H_MIN_DUTY_CYCLE_US (1000) // 1.00 ms
#define PANTILT_PWM_H_MAX_DUTY_CYCLE_US (2000) // 2.00 ms
pantilt_dev pantilt_inst(void *pwm_v_base, void *pwm_h_base);
void pantilt_init(pantilt_dev *dev);
void pantilt_configure_vertical(pantilt_dev *dev, uint32_t duty_cycle);
void pantilt_configure_horizontal(pantilt_dev *dev, uint32_t duty_cycle);
void pantilt_start_vertical(pantilt_dev *dev);
void pantilt_start_horizontal(pantilt_dev *dev);
void pantilt_stop_vertical(pantilt_dev *dev);
void pantilt_stop_horizontal(pantilt_dev *dev);
#endif /* __PANTILT_H__ */

View File

@ -0,0 +1,68 @@
#include "pwm.h"
#include "pwm_regs.h"
#include "iorw.h"
#define MICROSEC_TO_CLK(time, freq) ((time) * ((freq) / 1000000))
/**
* pwm_inst
*
* Instantiate a pwm device structure.
*
* @param base Base address of the component.
*/
pwm_dev pwm_inst(void *base) {
pwm_dev dev;
dev.base = base;
return dev;
}
/**
* pwm_init
*
* Initializes the pwm device. This function stops the controller.
*
* @param dev pwm device structure.
*/
void pwm_init(pwm_dev *dev) {
pwm_stop(dev);
}
/**
* pwm_configure
*
* Configure pwm component.
*
* @param dev pwm device structure.
* @param duty_cycle pwm duty cycle in us.
* @param period pwm period in us.
* @param module_frequency frequency at which the component is clocked.
*/
void pwm_configure(pwm_dev *dev, uint32_t duty_cycle, uint32_t period, uint32_t module_frequency) {
io_write_32(dev->base, PWM_PERIOD_OFST, MICROSEC_TO_CLK(period, module_frequency));
io_write_32(dev->base, PWM_DUTY_CYCLE_OFST, MICROSEC_TO_CLK(duty_cycle, module_frequency));
}
/**
* pwm_start
*
* Starts the pwm controller.
*
* @param dev pwm device structure.
*/
void pwm_start(pwm_dev *dev) {
io_write_32(dev->base, PWM_CTRL_OFST, PWM_CTRL_START_MASK);
}
/**
* pwm_stop
*
* Stops the pwm controller.
*
* @param dev pwm device structure.
*/
void pwm_stop(pwm_dev *dev) {
io_write_32(dev->base, PWM_CTRL_OFST, PWM_CTRL_START_MASK);
}

View File

@ -0,0 +1,21 @@
#ifndef __PWM_H__
#define __PWM_H__
#include <stdint.h>
/* pwm device structure */
typedef struct pwm_dev {
void *base; /* Base address of component */
} pwm_dev;
/*******************************************************************************
* Public API
******************************************************************************/
pwm_dev pwm_inst(void *base);
void pwm_init(pwm_dev *dev);
void pwm_configure(pwm_dev *dev, uint32_t duty_cycle, uint32_t period, uint32_t module_frequency);
void pwm_start(pwm_dev *dev);
void pwm_stop(pwm_dev *dev);
#endif /* __PWM_H__ */

View File

@ -0,0 +1,11 @@
#ifndef __PWM_REGS_H__
#define __PWM_REGS_H__
#define PWM_PERIOD_OFST (0 * 4) /* RW */
#define PWM_DUTY_CYCLE_OFST (1 * 4) /* RW */
#define PWM_CTRL_OFST (2 * 4) /* WO */
#define PWM_CTRL_STOP_MASK (0)
#define PWM_CTRL_START_MASK (1)
#endif /* __PWM_REGS_H__ */

View File

@ -0,0 +1,37 @@
#include "socfpga_cyclone5_de0_sockit.dts"
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#define VGA_SEQUENCER_REG_CSR 0x00
#define VGA_SEQUENCER_REG_HBP 0x04
#define VGA_SEQUENCER_REG_HFP 0x08
#define VGA_SEQUENCER_REG_VBP 0x0c
#define VGA_SEQUENCER_REG_VFP 0x10
#define VGA_SEQUENCER_REG_HDATA 0x14
#define VGA_SEQUENCER_REG_VDATA 0x18
#define VGA_SEQUENCER_REG_HSYNC 0x1c
#define VGA_SEQUENCER_REG_VSYNC 0x20
/ {
soc {
display {
compatible = "prsoc,display";
reg = <0xff200080 0x40 /* Frame manager <address span> */
0xff200000 0x80>; /* VGA sequencer <address span> */
interrupts = <GIC_SPI 40 IRQ_TYPE_EDGE_RISING>;
prsoc,screen-width = <480>;
prsoc,screen-height = <272>;
prsoc,buffer-width = <480>;
prsoc,buffer-height = <544>; // -> 2 buffers
prsoc,reg-init = <VGA_SEQUENCER_REG_VSYNC 10>,
<VGA_SEQUENCER_REG_VBP 2>,
<VGA_SEQUENCER_REG_VDATA 272>,
<VGA_SEQUENCER_REG_VFP 3>,
<VGA_SEQUENCER_REG_HSYNC 41>,
<VGA_SEQUENCER_REG_HBP 47>,
<VGA_SEQUENCER_REG_HDATA 480>,
<VGA_SEQUENCER_REG_HFP 8>,
<VGA_SEQUENCER_REG_CSR 1>;
};
};
};

View File

@ -0,0 +1,9 @@
obj-m += prsoc_fbdev.o
KERNEL_SOURCE_PATH='../../source/'
all:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERNEL_SOURCE_PATH) M=$(PWD) modules
clean:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERNEL_SOURCE_PATH) clean

View File

@ -0,0 +1,416 @@
/*
* @file prsoc_vga_fbdev
* @author Philemon Favrod
* @date 18 May 2016
* @brief The framebuffer Linux driver for the PrSoC extension board.
*
* This file is divided in two sections. The first contains the framebuffer
* driver code. The second contains the boilerplate code to create the
* device associated with the framebuffer. The latter allow us to use
* much less error-prone APIs (devm_* or dmam_*).
*
* More precisely, the LCD is viewed as a platform device, i.e. a device
* that is directly addressable from the CPU. Platform device are loaded
* based on their compatible string (here "prsoc,display"). In other words,
* once this driver is known to the kernel (c.f. insmod), the kernel will
* call its associated probe function if its associated compatible string
* is present in a device node (= an element of the device tree).
*
* In our case, the probe function is prsoc_display_platform_probe that you
* can find at the end of this file. Its main role is to allocate the resources
* based on what the device tree says. It uses the so-called managed API to
* do so. This API has the advantage of letting the kernel do the clean up based on
* whether or not the driver is loaded. It makes the code more readable.
* At the end of the probe function, the framebuffer is registered.
*
* For more information about this, here is a collection of resources that
* might be helpful:
* - https://www.kernel.org/doc/Documentation/driver-model/platform.txt
* -
*
* Revisions:
* 5/18/2016 Created (only for simple VGA)
* 5/28/2016 Adapted for TFT043
* 5/28/2016 Extended with mmap support
* 6/15/2016 Extend configurability from DT + panning
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/fb.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/types.h>
/* Offsets of the framebuffer manager's registers. */
#define FM_REG_FRAME_START_ADDRESS 0x00
#define FM_REG_FRAME_PIX_PER_LINE 0x04
#define FM_REG_FRAME_NUM_LINES 0x08
#define FM_REG_FRAME_EOL_BYTE_OFST 0x0C
#define FM_REG_CONTROL 0x10
#define FM_REG_BURST_COUNT 0x14
#define FM_CONTROL_ENABLE_DMA_MASK (1UL << 0)
#define FM_CONTROL_ENABLE_IRQ_MASK (1UL << 2)
#define FM_CONTROL_ACKNOWLEDGE_IRQ_MASK (1UL << 4)
/* Enclose the driver data. */
struct prsoc_display_drvdata {
uint8_t *fm_regs; /* a pointer to the frame manager's regs */
uint8_t *lcd_int_regs; /* a pointer to the LCD interface's regs */
uint32_t *front_buffer; /* a dmable frame buffer */
unsigned long front_buffer_phys; /* physical address of the frame buffer */
int irq;
};
#define FM_WR(DRVDATA, REG, VAL) \
iowrite32((VAL), (DRVDATA)->fm_regs + (REG))
#define LCD_INTERFACE_WR(DRVDATA, REG, VAL) \
iowrite32((VAL), (DRVDATA)->lcd_int_regs + (REG))
/* Framebuffer driver */
/* ISR called at the end of each frame. Called at the beginning
* of the vertical back porch, i.e. as soon as possible to avoid
* tearing effect. */
static irqreturn_t vsync_isr(int irq, void *data)
{
/*printk("IRQ received.\n");*/
//int i;
struct prsoc_display_drvdata *drvdata = data;
/* Acknowledge the IRQ */
FM_WR(drvdata, FM_REG_CONTROL, FM_CONTROL_ACKNOWLEDGE_IRQ_MASK);
return IRQ_HANDLED;
}
/* Defaults screen parameters */
static struct fb_fix_screeninfo prsocfb_fix_defaults = {
.id = "prsocfb",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_DIRECTCOLOR,
.accel = FB_ACCEL_NONE,
.ypanstep = 1 // support y panning
};
static struct fb_var_screeninfo prsocfb_var_defaults = {
.bits_per_pixel = 32,
.red = { .offset = 16, .length = 8 },
.green = { .offset = 8, .length = 8 },
.blue = { .offset = 0, .length = 8 }
};
uint32_t pseudo_palette[16];
static int prsocfb_setcoloreg(unsigned regno, unsigned red,
unsigned green, unsigned blue,
unsigned transp, struct fb_info *info)
{
if (regno >= 16)
return -EINVAL;
red *= 0xff;
green *= 0xff;
blue *= 0xff;
red /= 0xffff;
green /= 0xffff;
blue /= 0xffff;
pseudo_palette[regno] = (red << 16) | (green << 8) | blue;
return 0;
}
int prsocfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct prsoc_display_drvdata *drvdata = (struct prsoc_display_drvdata *)info->par;
uint32_t byte_offset;
if ((var->yoffset + var->yres > var->yres_virtual) ||
(var->xoffset + var->xres > var->xres_virtual))
{
return -EINVAL;
}
byte_offset = (var->yoffset * info->fix.line_length) +
(var->xoffset * (var->bits_per_pixel / 8));
FM_WR(drvdata, FM_REG_FRAME_START_ADDRESS, drvdata->front_buffer_phys + byte_offset);
return 0;
}
/* purpose: mmap the front buffer. */
static int prsocfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct prsoc_display_drvdata *drvdata = (struct prsoc_display_drvdata *)info->par;
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end - vma->vm_start;
unsigned long screen_size = info->var.xres_virtual * info->var.yres_virtual * sizeof(uint32_t);
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long pfn = -1;
void * pos = phys_to_virt(drvdata->front_buffer_phys) + offset;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); // non cachable page
vma->vm_flags |= VM_IO;
/* Compute the screen size in PAGE_SIZE. */
screen_size += PAGE_SIZE - 1;
screen_size >>= PAGE_SHIFT;
screen_size <<= PAGE_SHIFT;
/* Make sure that it maps only the back buffer */
if (offset + size > screen_size) {
printk(KERN_ERR "prsocfb: trying to mmap too much memory. %lu %lu %lu\n",
offset, size, screen_size);
return -EINVAL;
}
while (size > 0) {
/* Extract the page number of the current position
* in the buffer. */
pfn = virt_to_pfn(pos);
/* Map it in the user virtual memory. */
if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, vma->vm_page_prot)) {
printk(KERN_ERR "prsocfb: remap_pfn_range failed\n");
return -EAGAIN;
}
start += PAGE_SIZE;
pos += PAGE_SIZE;
if (size > PAGE_SIZE)
size -= PAGE_SIZE;
else
size = 0;
}
return 0;
}
static struct fb_ops prsocfb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = prsocfb_setcoloreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = prsocfb_mmap,
.fb_pan_display = prsocfb_pan_display
};
/* Platform driver */
/* Informs the kernel of the corresponding compatible string. */
static const struct of_device_id prsoc_display_device_ids[] = {
{ .compatible = "prsoc,display" },
{ }
};
MODULE_DEVICE_TABLE(of, prsoc_display_device_ids);
/* To understand Device tree parsing, see:
* - http://xillybus.com/tutorials/device-tree-zynq-4
* - http://xillybus.com/tutorials/device-tree-zynq-5
*/
#define EXTRACT_INT_FROM_DT_OR_FAIL(NP, PROP) ({ \
const void *property = of_get_property((NP), (PROP), NULL); \
if (!property) { \
printk(KERN_ERR "no '" PROP "' in the device tree."); \
return -EINVAL; \
} \
be32_to_cpup(property); \
})
/* Apply configuration from device tree. */
static int configure_from_dt(
struct platform_device *pdev,
struct prsoc_display_drvdata *drvdata,
struct fb_fix_screeninfo *fix_screeninfo,
struct fb_var_screeninfo *var_screeninfo)
{
struct resource *rsrc;
int err, i;
const __be32 *properties;
int len;
/* Extract a pointer to the device node. */
struct device_node *np = pdev->dev.of_node;
dma_addr_t phys;
/* Get the width and height properties. */
uint32_t screen_width = EXTRACT_INT_FROM_DT_OR_FAIL(np, "prsoc,screen-width");
uint32_t screen_height = EXTRACT_INT_FROM_DT_OR_FAIL(np, "prsoc,screen-height");
uint32_t buffer_width = EXTRACT_INT_FROM_DT_OR_FAIL(np, "prsoc,buffer-width");
uint32_t buffer_height = EXTRACT_INT_FROM_DT_OR_FAIL(np, "prsoc,buffer-height");
printk(KERN_INFO "According to the device tree, the screen is %ux%u and the buffer is %ux%u.",
screen_width, screen_height, buffer_width, buffer_height);
/* Maps the addresses of the registers of the framebuffer manager. */
rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drvdata->fm_regs = devm_ioremap_resource(&pdev->dev, rsrc);
if (IS_ERR(drvdata->fm_regs))
return PTR_ERR(drvdata->fm_regs);
printk(KERN_INFO "Framebuffer manager regs @ 0x%x-0x%x\n",
rsrc->start, rsrc->end);
/* Maps the addresses of the video interface. */
rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 1);
drvdata->lcd_int_regs = devm_ioremap_resource(&pdev->dev, rsrc);
if (IS_ERR(drvdata->lcd_int_regs))
return PTR_ERR(drvdata->lcd_int_regs);
printk(KERN_INFO "Interface regs @ 0x%x-0x%x\n", rsrc->start,
rsrc->end);
/* Register the ISR for vertical blanking notification. */
drvdata->irq = platform_get_irq(pdev, 0);
err = devm_request_irq(
&pdev->dev, drvdata->irq,
(irq_handler_t) vsync_isr,
0, "prsoc-fbdev", drvdata);
if (err) {
printk(KERN_ERR "couldn't register ISR. Is 'interrupts' " \
"field in the device tree?\n");
return -ENXIO;
}
/* Set the screeninfo to default values */
*fix_screeninfo = prsocfb_fix_defaults;
*var_screeninfo = prsocfb_var_defaults;
/* Set the size properties */
var_screeninfo->xres = screen_width;
var_screeninfo->yres = screen_height;
var_screeninfo->xres_virtual = buffer_width;
var_screeninfo->yres_virtual = buffer_height;
fix_screeninfo->line_length = screen_width * sizeof(uint32_t);
/* Allocate DMAble frame buffer. */
drvdata->front_buffer = dmam_alloc_coherent(
&pdev->dev,
buffer_width * buffer_height * sizeof(uint32_t),
&phys,
GFP_KERNEL);
if (!drvdata->front_buffer) {
printk(KERN_ERR "prsoc_fbdev: couldn't allocate a dmable buffer.\n");
return -ENOMEM;
}
drvdata->front_buffer_phys = (unsigned long)phys;
printk(KERN_INFO "DMABLE BUFFER @ 0x%lx\n", drvdata->front_buffer_phys);
/* Parse the reg-init sequence */
properties = of_get_property(pdev->dev.of_node, "prsoc,reg-init", &len);
if (!properties) {
printk(KERN_INFO "no 'prsoc,reg-init' property found in Device Tree.\n");
return 0; // reg-init is optional
}
len /= sizeof(__be32);
if (len % 2 != 0) {
printk(KERN_ERR "'prsoc,reg-init' in Device Tree should have format <ADDR1 VAL1>, <ADDR2 VAL2>, ...\n");
return -EINVAL;
}
printk(KERN_INFO "Initialize registers as specified in Device Tree:\n");
for (i = 0; i < len; i += 2) {
uint32_t offset = be32_to_cpup(properties + i);
uint32_t value = be32_to_cpup(properties + i + 1);
LCD_INTERFACE_WR(drvdata, offset, value);
printk(KERN_INFO "\tWrite 0x%x at offset 0x%x\n", value, offset);
}
return 0;
}
/*
* The following method is called when the driver is loaded.
* It collects information from the device tree.
*/
static int
prsoc_display_platform_probe(struct platform_device *pdev)
{
struct prsoc_display_drvdata *drvdata;
struct fb_info *info;
/* Defensive programming: let's make sure this is the right device. */
if (!of_match_device(prsoc_display_device_ids, &pdev->dev))
return -EINVAL;
/* Allocate the framebuffer. */
info = framebuffer_alloc(sizeof(struct prsoc_display_drvdata), &pdev->dev);
if (!info) {
return -ENOMEM;
}
/* Extract the allocated driver data structure. */
drvdata = (struct prsoc_display_drvdata *)info->par;
platform_set_drvdata(pdev, drvdata);
printk(KERN_INFO "Configure from Device Tree.\n");
configure_from_dt(pdev, drvdata, &info->fix, &info->var);
printk(KERN_INFO "Initialize the Frame Manager.\n");
FM_WR(drvdata, FM_REG_FRAME_START_ADDRESS, drvdata->front_buffer_phys);
FM_WR(drvdata, FM_REG_FRAME_PIX_PER_LINE, info->var.xres);
FM_WR(drvdata, FM_REG_FRAME_NUM_LINES, info->var.yres);
FM_WR(drvdata, FM_REG_FRAME_EOL_BYTE_OFST, 0);
FM_WR(drvdata, FM_REG_BURST_COUNT, 4);
FM_WR(drvdata, FM_REG_CONTROL, FM_CONTROL_ENABLE_DMA_MASK);
/* Enable IRQ */
// FM_WR(drvdata, FM_REG_CONTROL, FM_CONTROL_ENABLE_IRQ_MASK);
/* Configure the framebuffer */
info->screen_base = (void *)drvdata->front_buffer;
info->screen_size = info->var.xres * info->var.yres * sizeof(uint32_t);
info->fbops = &prsocfb_ops;
info->pseudo_palette = pseudo_palette;
info->flags = FBINFO_DEFAULT;
if (fb_alloc_cmap(&info->cmap, 256, 0))
return -ENOMEM;
return register_framebuffer(info);
}
int prsoc_display_platform_remove(struct platform_device *pdev)
{
struct prsoc_display_drvdata *drvdata = platform_get_drvdata(pdev);
struct fb_info *info = container_of((void *)drvdata, struct fb_info, par);
unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
return 0;
}
static struct platform_driver prsoc_display_pdriver = {
.probe = prsoc_display_platform_probe,
.driver = {
.name = "PrSoC displays",
.owner = THIS_MODULE,
.of_match_table = prsoc_display_device_ids,
},
};
MODULE_LICENSE("GPL");
module_platform_driver(prsoc_display_pdriver);

View File

@ -0,0 +1,23 @@
#!/bin/bash -x
# apt sources
# uncomment the "deb" lines (no need to uncomment "deb src" lines)
# Edit the “/etc/apt/sources.list” file to configure the package manager. This
# file contains a list of mirrors that the package manager queries. By default,
# this file has all fields commented out, so the package manager will not have
# access to any mirrors. The following command uncomments all commented out
# lines starting with "deb". These contain the mirrors we are interested in.
sudo perl -pi -e 's/^#+\s+(deb\s+http)/$1/g' "/etc/apt/sources.list"
# When writing our linux applications, we want to use ARM DS-5s remote
# debugging feature to automatically transfer our binaries to the target device
# and to start a debugging session. The remote debugging feature requires an SSH
# server and a remote gdb server to be available on the target. These are easy
# to install as we have a package manager available
sudo apt update
sudo apt -y install ssh gdbserver
# Allow root SSH login with password (needed so we can use ARM DS-5 for remote
# debugging)
sudo perl -pi -e 's/^(PermitRootLogin) without-password$/$1 yes/g' "/etc/ssh/sshd_config"

View File

@ -0,0 +1,94 @@
#!/bin/bash -x
# Configure the locale to have proper language support.
localedef -i en_US -c -f UTF-8 en_US.UTF-8
dpkg-reconfigure locales
# Configure the timezone.
echo "Europe/Zurich" > "/etc/timezone"
dpkg-reconfigure -f noninteractive tzdata
# Set the machines hostname.
echo "DE0-Nano-SoC" > "/etc/hostname"
tee "/etc/hosts" >"/dev/null" <<EOF
127.0.0.1 localhost
127.0.1.1 DE0-Nano-SoC
EOF
# Create the “/etc/network/interfaces” file that describes the network
# interfaces available on the board.
tee "/etc/network/interfaces" > "/dev/null" <<EOF
# interfaces(5) file used by ifup(8) and ifdown(8)
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto eth0
iface eth0 inet static
address 10.42.0.2
netmask 255.255.255.0
gateway 10.42.0.1
EOF
# DNS configuration for name resolution. We use google's public DNS server here.
sudo tee "/etc/resolv.conf" > "/dev/null" <<EOF
nameserver 8.8.8.8
EOF
# Configure Ubuntu Core to display a login shell on the serial console once the
# kernel boots. We had previously configured U-Boot to supply the command-line
# argument "console=ttyS0,115200" to the linux kernel. This argument instructs
# the kernel to use serial console “ttyS0” as the boot shell, so here we choose
# to use the same serial console for the login shell-
tee "/etc/init/ttyS0.conf" > "/dev/null" <<EOF
# ttyS0 - getty
#
# This service maintains a getty on ttyS0
description "Get a getty on ttyS0"
start on runlevel [2345]
stop on runlevel [016]
respawn
exec /sbin/getty -L 115200 ttyS0 vt102
EOF
# Create a user and a password. In this example, we create a user called
# “sahand” with password "1234". Note that we compute an encrypted version of
# the password, because useradd does not allow plain text passwords to be used
# in non-interactive mode.
username="sahand"
password="1234"
encrypted_password="$(perl -e 'printf("%s\n", crypt($ARGV[0], "password"))' "${password}")"
useradd -m -p "${encrypted_password}" -s "/bin/bash" "${username}"
# Ubuntu requires the admin to be part of the "adm" and "sudo" groups, so add
# the previously-created user to the 2 groups.
addgroup ${username} adm
addgroup ${username} sudo
# Set root password to "1234" (same as previously-created user).
echo -e "${password}\n${password}\n" | passwd root
# Remove "/rootfs_config.sh" from /etc/rc.local to avoid reconfiguring system on
# next boot
tee "/etc/rc.local" > "/dev/null" <<EOF
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
exit 0
EOF