mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-09 11:50:40 +00:00
Fixed restart bug in multi-core Breakout and librified audio (CPU and DMA)
This commit is contained in:
parent
447e41536a
commit
c279397cba
6 changed files with 172 additions and 92 deletions
|
@ -156,10 +156,10 @@ void moveObject(volatile struct Object *object, int x, int y)
|
||||||
const int ballradius = 15;
|
const int ballradius = 15;
|
||||||
const int paddlewidth = 80;
|
const int paddlewidth = 80;
|
||||||
|
|
||||||
volatile unsigned char dir = 50;
|
volatile unsigned char dir;
|
||||||
volatile unsigned int numobjs = 0;
|
volatile unsigned int numobjs;
|
||||||
|
|
||||||
volatile struct Object *objects = (struct Object *)SAFE_ADDRESS;
|
volatile struct Object *objects = (struct Object *)HEAP_ADDRESS;
|
||||||
volatile struct Object *ball;
|
volatile struct Object *ball;
|
||||||
volatile struct Object *paddle;
|
volatile struct Object *paddle;
|
||||||
volatile struct Object *scoreboard;
|
volatile struct Object *scoreboard;
|
||||||
|
@ -167,6 +167,9 @@ volatile struct Object *endgame;
|
||||||
|
|
||||||
void breakout_init()
|
void breakout_init()
|
||||||
{
|
{
|
||||||
|
numobjs = 0;
|
||||||
|
dir = 50;
|
||||||
|
|
||||||
initBricks();
|
initBricks();
|
||||||
initBall();
|
initBall();
|
||||||
initPaddle();
|
initPaddle();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Heap memory allocation
|
// Heap memory allocation
|
||||||
#define SAFE_ADDRESS 0x00400000 // Somewhere safe to store a lot of data
|
#define HEAP_ADDRESS 0x00400000 // Somewhere safe to store a lot of data
|
||||||
|
|
||||||
// The screen
|
// The screen
|
||||||
#define WIDTH 1920
|
#define WIDTH 1920
|
||||||
|
|
|
@ -1,77 +1,14 @@
|
||||||
#include "include/fb.h"
|
|
||||||
#include "include/io.h"
|
|
||||||
#include "include/multicore.h"
|
#include "include/multicore.h"
|
||||||
|
#include "include/audio.h"
|
||||||
#define PWM_BASE (PERIPHERAL_BASE + 0x20C000 + 0x800) /* PWM1 register base address on RPi4 */
|
|
||||||
#define PWM_LEGACY_BASE (LEGACY_BASE + 0x20C000 + 0x800) /* PWM1 register base legacy address on RPi4 */
|
|
||||||
#define CLOCK_BASE (PERIPHERAL_BASE + 0x101000)
|
|
||||||
|
|
||||||
#define BCM2711_PWMCLK_CNTL 40
|
|
||||||
#define BCM2711_PWMCLK_DIV 41
|
|
||||||
#define PM_PASSWORD 0x5A000000
|
|
||||||
|
|
||||||
#define BCM2711_PWM_CONTROL 0
|
|
||||||
#define BCM2711_PWM_STATUS 1
|
|
||||||
#define BCM2711_PWM_DMAC 2
|
|
||||||
#define BCM2711_PWM0_RANGE 4
|
|
||||||
#define BCM2711_PWM0_DATA 5
|
|
||||||
#define BCM2711_PWM_FIFO 6
|
|
||||||
#define BCM2711_PWM1_RANGE 8
|
|
||||||
#define BCM2711_PWM1_DATA 9
|
|
||||||
|
|
||||||
#define BCM2711_PWM1_USEFIFO 0x2000 /* Data from FIFO */
|
|
||||||
#define BCM2711_PWM1_ENABLE 0x0100 /* Channel enable */
|
|
||||||
#define BCM2711_PWM0_USEFIFO 0x0020 /* Data from FIFO */
|
|
||||||
#define BCM2711_PWM0_ENABLE 0x0001 /* Channel enable */
|
|
||||||
#define BCM2711_PWM_ENAB 0x80000000 /* PWM DMA Configuration: DMA Enable (bit 31 set) */
|
|
||||||
|
|
||||||
#define BCM2711_GAPO2 0x20
|
|
||||||
#define BCM2711_GAPO1 0x10
|
|
||||||
#define BCM2711_RERR1 0x8
|
|
||||||
#define BCM2711_WERR1 0x4
|
|
||||||
#define BCM2711_FULL1 0x1
|
|
||||||
#define ERRORMASK (BCM2711_GAPO2 | BCM2711_GAPO1 | BCM2711_RERR1 | BCM2711_WERR1)
|
|
||||||
|
|
||||||
volatile unsigned* clk = (void*)CLOCK_BASE;
|
|
||||||
volatile unsigned* pwm = (void*)PWM_BASE;
|
|
||||||
|
|
||||||
void audio_init(void)
|
|
||||||
{
|
|
||||||
gpio_useAsAlt0(40); // Ensure PWM1 is mapped to GPIO 40/41
|
|
||||||
gpio_useAsAlt0(41);
|
|
||||||
wait_msec(2);
|
|
||||||
|
|
||||||
// Setup clock
|
|
||||||
|
|
||||||
*(clk + BCM2711_PWMCLK_CNTL) = PM_PASSWORD | (1 << 5); // Stop clock
|
|
||||||
wait_msec(2);
|
|
||||||
|
|
||||||
int idiv = 2;
|
|
||||||
*(clk + BCM2711_PWMCLK_DIV) = PM_PASSWORD | (idiv<<12);
|
|
||||||
*(clk + BCM2711_PWMCLK_CNTL) = PM_PASSWORD | 16 | 1; // Osc + Enable
|
|
||||||
wait_msec(2);
|
|
||||||
|
|
||||||
// Setup PWM
|
|
||||||
|
|
||||||
*(pwm + BCM2711_PWM_CONTROL) = 0;
|
|
||||||
wait_msec(2);
|
|
||||||
|
|
||||||
*(pwm+BCM2711_PWM0_RANGE) = 0x264; // 44.1khz, Stereo, 8-bit (54Mhz / 44100 / 2)
|
|
||||||
*(pwm+BCM2711_PWM1_RANGE) = 0x264;
|
|
||||||
|
|
||||||
*(pwm+BCM2711_PWM_CONTROL) =
|
|
||||||
BCM2711_PWM1_USEFIFO |
|
|
||||||
BCM2711_PWM1_ENABLE |
|
|
||||||
BCM2711_PWM0_USEFIFO |
|
|
||||||
BCM2711_PWM0_ENABLE | 1<<6;
|
|
||||||
}
|
|
||||||
|
|
||||||
void snd_core(void)
|
void snd_core(void)
|
||||||
{
|
{
|
||||||
clear_core2();
|
clear_core2();
|
||||||
|
|
||||||
int i=0;
|
// Initialise the audio
|
||||||
long status;
|
audio_init();
|
||||||
|
|
||||||
|
// Write data out to FIFO and loop infinitely
|
||||||
|
|
||||||
extern unsigned char _binary_bin_audio_bin_start[];
|
extern unsigned char _binary_bin_audio_bin_start[];
|
||||||
extern unsigned char _binary_bin_audio_bin_size[];
|
extern unsigned char _binary_bin_audio_bin_size[];
|
||||||
|
@ -79,24 +16,5 @@ void snd_core(void)
|
||||||
unsigned int size = (long)&_binary_bin_audio_bin_size;
|
unsigned int size = (long)&_binary_bin_audio_bin_size;
|
||||||
unsigned char *data = &(_binary_bin_audio_bin_start[0]);
|
unsigned char *data = &(_binary_bin_audio_bin_start[0]);
|
||||||
|
|
||||||
// Initialise the audio
|
while (1) audio_play_cpu(data, size);
|
||||||
audio_init();
|
|
||||||
|
|
||||||
// Write data out to FIFO and loop infinitely
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
while (i < size) {
|
|
||||||
status = *(pwm + BCM2711_PWM_STATUS);
|
|
||||||
if (!(status & BCM2711_FULL1)) {
|
|
||||||
*(pwm+BCM2711_PWM_FIFO) = *(data + i);
|
|
||||||
i++;
|
|
||||||
*(pwm+BCM2711_PWM_FIFO) = *(data + i);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if ((status & ERRORMASK)) {
|
|
||||||
*(pwm+BCM2711_PWM_STATUS) = ERRORMASK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i=0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
59
part11-breakout-smp/include/audio.h
Normal file
59
part11-breakout-smp/include/audio.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
#define PWM_BASE (PERIPHERAL_BASE + 0x20C000 + 0x800) /* PWM1 register base address on RPi4 */
|
||||||
|
#define PWM_LEGACY_BASE (LEGACY_BASE + 0x20C000 + 0x800) /* PWM1 register base legacy address on RPi4 */
|
||||||
|
#define CLOCK_BASE (PERIPHERAL_BASE + 0x101000)
|
||||||
|
#define DMA_BASE (PERIPHERAL_BASE + 0x007100) /* DMA register base address */
|
||||||
|
#define DMA_ENABLE (DMA_BASE + 0xFF0) /* DMA global enable bits */
|
||||||
|
|
||||||
|
#define DMA_ADDRESS 0x00500000 /* A safe address to use for our DMA transfer */
|
||||||
|
|
||||||
|
#define BCM2711_PWMCLK_CNTL 40
|
||||||
|
#define BCM2711_PWMCLK_DIV 41
|
||||||
|
#define PM_PASSWORD 0x5A000000
|
||||||
|
|
||||||
|
#define BCM2711_PWM_CONTROL 0
|
||||||
|
#define BCM2711_PWM_STATUS 1
|
||||||
|
#define BCM2711_PWM_DMAC 2
|
||||||
|
#define BCM2711_PWM0_RANGE 4
|
||||||
|
#define BCM2711_PWM0_DATA 5
|
||||||
|
#define BCM2711_PWM_FIFO 6
|
||||||
|
#define BCM2711_PWM1_RANGE 8
|
||||||
|
#define BCM2711_PWM1_DATA 9
|
||||||
|
|
||||||
|
#define BCM2711_PWM1_USEFIFO 0x2000 /* Data from FIFO */
|
||||||
|
#define BCM2711_PWM1_ENABLE 0x0100 /* Channel enable */
|
||||||
|
#define BCM2711_PWM0_USEFIFO 0x0020 /* Data from FIFO */
|
||||||
|
#define BCM2711_PWM0_ENABLE 0x0001 /* Channel enable */
|
||||||
|
#define BCM2711_PWM_ENAB 0x80000000 /* PWM DMA Configuration: DMA Enable (bit 31 set) */
|
||||||
|
|
||||||
|
#define BCM2711_GAPO2 0x20
|
||||||
|
#define BCM2711_GAPO1 0x10
|
||||||
|
#define BCM2711_RERR1 0x8
|
||||||
|
#define BCM2711_WERR1 0x4
|
||||||
|
#define BCM2711_FULL1 0x1
|
||||||
|
#define ERRORMASK (BCM2711_GAPO2 | BCM2711_GAPO1 | BCM2711_RERR1 | BCM2711_WERR1)
|
||||||
|
|
||||||
|
#define DMA_CS 0 /* Control/status register offset for DMA channel 0 */
|
||||||
|
#define DMA_CONBLK_AD 1
|
||||||
|
#define DMA_EN1 1 << 1 /* Enable DMA engine 1 */
|
||||||
|
#define DMA_ACTIVE 1 /* Active bit set */
|
||||||
|
#define DMA_DEST_DREQ 0x40 /* Use DREQ to pace peripheral writes */
|
||||||
|
#define DMA_PERMAP_1 0x10000 /* PWM1 peripheral for DREQ */
|
||||||
|
#define DMA_SRC_INC 0x100 /* Increment source address */
|
||||||
|
|
||||||
|
struct dma_cb {
|
||||||
|
unsigned int ti;
|
||||||
|
unsigned int source_ad;
|
||||||
|
unsigned int dest_ad;
|
||||||
|
unsigned int txfr_len;
|
||||||
|
unsigned int stride;
|
||||||
|
unsigned int nextconbk;
|
||||||
|
unsigned int null1;
|
||||||
|
unsigned int null2;
|
||||||
|
} __attribute__((aligned(32)));
|
||||||
|
|
||||||
|
void audio_init(void);
|
||||||
|
void audio_play_cpu(unsigned char *data, unsigned int size);
|
||||||
|
void audio_play_dma(unsigned char *data, unsigned int size);
|
||||||
|
void audio_wait_dma(void);
|
|
@ -1,4 +1,5 @@
|
||||||
#define PERIPHERAL_BASE 0xFE000000
|
#define PERIPHERAL_BASE 0xFE000000
|
||||||
|
#define LEGACY_BASE 0x7E000000
|
||||||
|
|
||||||
void uart_init();
|
void uart_init();
|
||||||
void uart_writeText(char *buffer);
|
void uart_writeText(char *buffer);
|
||||||
|
|
99
part11-breakout-smp/lib/audio.c
Normal file
99
part11-breakout-smp/lib/audio.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#include "../include/audio.h"
|
||||||
|
#include "../include/fb.h"
|
||||||
|
|
||||||
|
volatile unsigned* clk = (void*)CLOCK_BASE;
|
||||||
|
volatile unsigned* pwm = (void*)PWM_BASE;
|
||||||
|
volatile unsigned* dma = (void*)DMA_BASE;
|
||||||
|
volatile unsigned* dmae = (void*)DMA_ENABLE;
|
||||||
|
volatile unsigned* safe = (void*)DMA_ADDRESS;
|
||||||
|
struct dma_cb playback_cb;
|
||||||
|
|
||||||
|
void audio_init(void)
|
||||||
|
{
|
||||||
|
gpio_useAsAlt0(40); // Ensure PWM1 is mapped to GPIO 40/41
|
||||||
|
gpio_useAsAlt0(41);
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
// Setup clock
|
||||||
|
|
||||||
|
*(clk + BCM2711_PWMCLK_CNTL) = PM_PASSWORD | (1 << 5); // Stop clock
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
int idiv = 2;
|
||||||
|
*(clk + BCM2711_PWMCLK_DIV) = PM_PASSWORD | (idiv<<12);
|
||||||
|
*(clk + BCM2711_PWMCLK_CNTL) = PM_PASSWORD | 16 | 1; // Osc + Enable
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
// Setup PWM
|
||||||
|
|
||||||
|
*(pwm + BCM2711_PWM_CONTROL) = 0;
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
*(pwm+BCM2711_PWM0_RANGE) = 0x264; // 44.1khz, Stereo, 8-bit (54Mhz / 44100 / 2)
|
||||||
|
*(pwm+BCM2711_PWM1_RANGE) = 0x264;
|
||||||
|
|
||||||
|
*(pwm+BCM2711_PWM_CONTROL) =
|
||||||
|
BCM2711_PWM1_USEFIFO |
|
||||||
|
BCM2711_PWM1_ENABLE |
|
||||||
|
BCM2711_PWM0_USEFIFO |
|
||||||
|
BCM2711_PWM0_ENABLE | 1<<6;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_play_cpu(unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
long status;
|
||||||
|
|
||||||
|
// Write data out to FIFO
|
||||||
|
|
||||||
|
while (i < size) {
|
||||||
|
status = *(pwm + BCM2711_PWM_STATUS);
|
||||||
|
if (!(status & BCM2711_FULL1)) {
|
||||||
|
*(pwm+BCM2711_PWM_FIFO) = *(data + i);
|
||||||
|
i++;
|
||||||
|
*(pwm+BCM2711_PWM_FIFO) = *(data + i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if ((status & ERRORMASK)) {
|
||||||
|
*(pwm+BCM2711_PWM_STATUS) = ERRORMASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_play_dma(unsigned char *data, unsigned int size)
|
||||||
|
{
|
||||||
|
// Convert data (we expect 8-bit samples, but need to convert them to 32-bit words)
|
||||||
|
|
||||||
|
for (int i=0;i<size;i++) *(safe+i) = *(data+i);
|
||||||
|
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
// Set up control block
|
||||||
|
|
||||||
|
playback_cb.ti = DMA_DEST_DREQ + DMA_PERMAP_1 + DMA_SRC_INC;
|
||||||
|
playback_cb.source_ad = DMA_ADDRESS;
|
||||||
|
playback_cb.dest_ad = PWM_LEGACY_BASE + 0x18; // Points to PWM_FIFO
|
||||||
|
playback_cb.txfr_len = size * 4; // They're unsigned ints now, not unsigned chars
|
||||||
|
playback_cb.stride = 0x00;
|
||||||
|
playback_cb.nextconbk = 0x00; // Don't loop
|
||||||
|
playback_cb.null1 = 0x00;
|
||||||
|
playback_cb.null2 = 0x00;
|
||||||
|
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
// Enable DMA
|
||||||
|
|
||||||
|
*(pwm+BCM2711_PWM_DMAC) =
|
||||||
|
BCM2711_PWM_ENAB + 0x0707; // Bits 0-7 Threshold For DREQ Signal = 1, Bits 8-15 Threshold For PANIC Signal = 0
|
||||||
|
*dmae = DMA_EN1;
|
||||||
|
*(dma+DMA_CONBLK_AD) = (long)&playback_cb; // checked and correct
|
||||||
|
|
||||||
|
wait_msec(2);
|
||||||
|
|
||||||
|
*(dma+DMA_CS) = DMA_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_wait_dma(void)
|
||||||
|
{
|
||||||
|
while (*(dma+DMA_CS) & 0x1); // Wait for DMA transfer to finish - we could do anything here instead!
|
||||||
|
}
|
Loading…
Reference in a new issue