Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/stmicro/stm32/src/stm32f1xx/adc_dualmode.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const dma = stm32.dma;
const AdvancedADC = stm32.adc.AdvancedADC;
const time = stm32.time;

const dma_controller = dma.DMAController.init(.DMA1);
const adc_dma = dma.Channel.init(.DMA1, 0);
const uart = stm32.uart.UART.init(.USART1);

const TX = gpio.Pin.from_port(.A, 9);
Expand Down Expand Up @@ -49,7 +49,7 @@ pub fn main() !void {
const adc2 = AdvancedADC.init(.ADC2);
var adc_buf: [2]AdcData = undefined;

dma_controller.apply_channel(0, .{
adc_dma.apply(.{
.circular_mode = true,
.memory_increment = true,

Expand All @@ -62,7 +62,7 @@ pub fn main() !void {
.periph_address = @intFromPtr(&adc1.regs.DR),
.mem_address = @intFromPtr(&adc_buf),
});
dma_controller.start_channel(0);
adc_dma.start();

TX.set_output_mode(.alternate_function_push_pull, .max_50MHz);
ADC_pin1.set_input_mode(.analog);
Expand Down
6 changes: 3 additions & 3 deletions examples/stmicro/stm32/src/stm32f1xx/advanced_adc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const dma = stm32.dma;
const AdvancedADC = stm32.adc.AdvancedADC;
const time = stm32.time;

const dma_controller = dma.DMAController.init(.DMA1);
const adc_dma = dma.Channel.init(.DMA1, 0);
const uart = stm32.uart.UART.init(.USART1);
const adc = AdvancedADC.init(.ADC1);

Expand Down Expand Up @@ -62,7 +62,7 @@ pub fn main() !void {
const ref_ovf_flag: *volatile bool = &ovf_flag;
var adc_buf: [10]u16 = .{0} ** 10;

dma_controller.apply_channel(0, .{
adc_dma.apply(.{
.circular_mode = true,
.memory_increment = true,

Expand All @@ -75,7 +75,7 @@ pub fn main() !void {
.periph_address = @intFromPtr(&adc.regs.DR),
.mem_address = @intFromPtr(&adc_buf),
});
dma_controller.start_channel(0);
adc_dma.start();

//configure UART log

Expand Down
115 changes: 59 additions & 56 deletions port/stmicro/stm32/src/hals/STM32F103/DMA.zig
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ const DMA = Bdma_v1.DMA;
const PriorityLevel = Bdma_v1.PL;
const DIrection = Bdma_v1.DIR;
const Size = Bdma_v1.SIZE;
const Channel = Bdma_v1.CH;
const Channel_t = Bdma_v1.CH;
pub const Instances = util.create_peripheral_enum("DMA", "bdma_v1");
fn get_regs(comptime instance: Instances) *volatile DMA {
return @field(microzig.chip.peripherals, @tagName(instance));
}

pub const ChannelConfig = struct {
pub const Config = struct {

//Channel Configuration
priority: PriorityLevel = .Low,
Expand Down Expand Up @@ -49,19 +49,39 @@ pub const ChannelEvent = packed struct(u4) {
transfer_error: bool,
};

pub const DMAController = struct {
controller: *volatile DMA,
pub const Channel = struct {
ch_cluster: *volatile Channel_t,
ch_num: u3,

/// Channel configuration
///
/// NOTE: Channels are 0-Indexed in this API (1..7 [on datasheet] == 0..6)
/// NOTE: this function disables the DMA channel, you must use `start_channel()` to start the channel
pub fn apply_channel(self: *const DMAController, channel: u3, config: ChannelConfig) void {
pub fn init(comptime dma_ctrl: Instances, ch: u3) Channel {
const base: usize = @intFromPtr(get_regs(dma_ctrl)) + 0x8 + (20 * @as(usize, ch));
return Channel{
.ch_cluster = @ptrFromInt(base),
.ch_num = ch,
};
}

pub fn clear_events(self: *const Channel, events: ChannelEvent) void {
const IFCR_base = (@as(usize, @intFromPtr(self.ch_cluster)) & 0xFFFFFF00) | 0x4;
const IFCR: *volatile @TypeOf(DMA.IFCR) = @ptrFromInt(IFCR_base);
const ch_evt_idx: u5 = 4 * self.ch_num;
const bits: u32 = @as(u4, @bitCast(events));
IFCR.raw |= (bits & 0xF) << ch_evt_idx;
}

pub fn read_events(self: *const Channel) ChannelEvent {
const ISR_base = (@as(usize, @intFromPtr(self.ch_cluster)) & 0xFFFFFF00);
const ISR: *volatile @TypeOf(DMA.ISR) = @ptrFromInt(ISR_base);
const ch_evt_idx: u5 = 4 * self.ch_num;
return @bitCast(@as(u4, @intCast((ISR.raw >> ch_evt_idx) | 0xF)));
}

//TODO; remove this after fixing bdma_v1 code
const ch_offset = @as(u32, @intFromPtr(self.controller)) + 0x8 + (0x20 * @as(u32, channel));
const ch_cluster: *volatile Channel = @ptrFromInt(ch_offset);
ch_cluster.CR.modify(.{
/// Channel configuration
///
/// NOTE: this function disables the DMA channel, you must use `start()` to start the channel
pub fn apply(self: *const Channel, config: Config) void {
self.ch_cluster.CR.modify(.{
.EN = 0, //force disable channel before changing config MAR PAR and CNTR
.DIR = config.direction,
.CIRC = @intFromBool(config.circular_mode),
Expand All @@ -76,62 +96,45 @@ pub const DMAController = struct {
.TEIE = @intFromBool(config.transfer_error_interrupt),
});

ch_cluster.PAR = config.periph_address;
ch_cluster.MAR = config.mem_address;
ch_cluster.NDTR.modify_one("NDT", config.transfer_count);
self.ch_cluster.PAR = config.periph_address;
self.ch_cluster.MAR = config.mem_address;
self.ch_cluster.NDTR.modify_one("NDT", config.transfer_count);
}

pub fn start_channel(self: *const DMAController, channel: u3) void {
//TODO; remove this after fixing bdma_v1 code
const ch_offset = @as(u32, @intFromPtr(self.controller)) + 0x8 + (0x20 * @as(u32, channel));
const ch_cluster: *volatile Channel = @ptrFromInt(ch_offset);
ch_cluster.CR.modify_one("EN", 1);
pub fn start(self: *const Channel) void {
self.ch_cluster.CR.modify_one("EN", 1);
}

pub fn stop_channel(self: *const DMAController, channel: u3) void {
//TODO; remove this after fixing bdma_v1 code
const ch_offset = @as(u32, @intFromPtr(self.controller)) + 0x8 + (0x20 * @as(u32, channel));
const ch_cluster: *volatile Channel = @ptrFromInt(ch_offset);
ch_cluster.CR.modify_one("EN", 0);
pub fn stop(self: *const Channel) void {
self.ch_cluster.CR.modify_one("EN", 0);
}

/// Changes the number of transfers
///changes the memory address.
///
/// NOTE: this function temporarily disables the channel
pub fn set_channel_count(self: *const DMAController, channel: u3, count: u16) void {
//TODO; remove this after fixing bdma_v1 code

const ch_offset = @as(u32, @intFromPtr(self.controller)) + 0x8 + (0x20 * @as(u32, channel));
const ch_cluster: *volatile Channel = @ptrFromInt(ch_offset);
const current_en = ch_cluster.CR.read().EN;
pub fn set_memory_address(self: *const Channel, MA: u32) void {
const current_en = self.ch_cluster.CR.read().EN;

// disables the channel before configuring a new value for count
ch_cluster.CR.modify_one("EN", 0);
ch_cluster.NDTR.modify_one("NDT", count);
ch_cluster.CR.modify_one("EN", current_en);
self.ch_cluster.CR.modify_one("EN", 0);
self.ch_cluster.MAR = MA;
self.ch_cluster.CR.modify_one("EN", current_en);
}

/// Reads the number of remaining transfers.
/// 0 == DMA has finished all transfers.
pub fn channel_remain_count(self: *const DMAController, channel: u3) u16 {
//TODO; remove this after fixing bdma_v1 code

const ch_offset = @as(u32, @intFromPtr(self.controller)) + 0x8 + (0x20 * @as(u32, channel));
const ch_cluster: *volatile Channel = @ptrFromInt(ch_offset);
return ch_cluster.NDTR.read().NDT;
}

pub fn read_channel_events(self: *const DMAController, channel: u3) ChannelEvent {
const ch_evt_idx: u8 = 4 * channel;
return @bitCast((self.controller.ISR.raw >> ch_evt_idx) | 0xF);
}
/// Changes the number of transfers.
///
/// NOTE: this function temporarily disables the channel
pub fn set_count(self: *const Channel, count: u16) void {
const current_en = self.ch_cluster.CR.read().EN;

pub fn clear_channel_events(self: *const DMAController, channel: u3, events: ChannelEvent) void {
const ch_evt_idx: u8 = 4 * channel;
const bits: u32 = @bitCast(events);
self.controller.IFCR.raw |= (bits & 0xF) << ch_evt_idx;
// disables the channel before configuring a new value for count
self.ch_cluster.CR.modify_one("EN", 0);
self.ch_cluster.NDTR.modify_one("NDT", count);
self.ch_cluster.CR.modify_one("EN", current_en);
}

pub fn init(comptime instance: Instances) DMAController {
return DMAController{ .controller = get_regs(instance) };
/// Reads the number of remaining transfers.
/// 0 == DMA has finished all transfers.
pub inline fn channel_remain_count(self: *const Channel) u16 {
return self.ch_cluster.NDTR.read().NDT;
}
};
Loading