请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
部件号:TM4C123GH6PM 我有一个 LED 条(ws2812b/SMD5050)。 我在条带上有30个 LED,需要发射24个脉冲(每种颜色8位)。
我生成了一个720Byte 长数组,用于保持 PWM 脉冲持续时间。 在一个周期结束后,我使用 ISR 重新加载 PWM。
现在我想关闭 MCU 的加载并使用 DMA。 如何做到这一点?
我附上我的(Zephyr)代码。 因此,我应该很容易知道我应该在哪里添加 DMA。
#include <stddef.h>
#include <stdint.h>
#include <kernel.h>
#include <drivers/gpio.h>
#include <sys/util.h>
#include <devicetree.h>
#include "../../ti_drv/cfg_tiva.h"
#include "../../ti_drv/sysctl_tiva.h"
#include "../../ti_drv/ti_tiva_dt.h"
#include "../../ti_drv/pinmux_tiva.h"
#include "../../ti_drv/timers_tiva.h"
#include "../../tier_drv/led1wire.h"
DEVICE_DECLARE(ws2812b_0);
#define LED_NUM 30
#define LED_BYTE_NUM 3*8*LED_NUM
// ws2812b also called SMD5050
// typical max BGR = 255, 176, 240
typedef struct ws2812b_s {
struct k_mutex gm;
volatile unsigned int idx;
uint8_t ledBytes[LED_BYTE_NUM];
// struct k_spinlock sl;
} ws2812b_t;
static ws2812b_t ws2812b;
#ifdef CONFIG_ZERO_LATENCY_IRQS
#define INTR_EXTRA_FLAG IRQ_ZERO_LATENCY
#else
#define INTR_EXTRA_FLAG 0
#endif
/*
static const uint8_t rgb_lookup_r [256] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240};
static const uint8_t rgb_lookup_g [256] = {0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26, 27, 28, 28, 29, 30, 31, 31, 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 48, 49, 49, 50, 51, 51, 52, 53, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60, 60, 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 68, 69, 69, 70, 71, 71, 72, 73, 73, 74, 75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 84, 85, 86, 86, 87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 96, 97, 98, 98, 99, 100, 100, 101, 102, 102, 103, 104, 104, 105, 106, 106, 107, 108, 109, 109, 110, 111, 111, 112, 113, 113, 114, 115, 115, 116, 117, 118, 118, 119, 120, 120, 121, 122, 122, 123, 124, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131, 131, 132, 133, 133, 134, 135, 135, 136, 137, 138, 138, 139, 140, 140, 141, 142, 142, 143, 144, 144, 145, 146, 147, 147, 148, 149, 149, 150, 151, 151, 152, 153, 153, 154, 155, 155, 156, 157, 158, 158, 159, 160, 160, 161, 162, 162, 163, 164, 164, 165, 166, 167, 167, 168, 169, 169, 170, 171, 171, 172, 173, 173, 174, 175, 176};
static const uint8_t rgb_lookup_b [256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
*/
static unsigned int ws2812b_getAmount(const struct device *dev){
return LED_NUM;
}
static void set_colour(const unsigned int offs, const uint8_t colour) {
// colour is coded MSBit -> LSBit
// so we need to flip the bits
uint8_t v = colour;
for (unsigned int i = 0; i < 8; i++) {
if(v & 0x1) {
ws2812b.ledBytes[offs+7-i] = 36;
} else {
ws2812b.ledBytes[offs+7-i] = 68;
}
v>>=1;
}
}
static void ws2812b_set8bitRGB(const struct device *dev, const unsigned int indx, const uint8_t red, const uint8_t green, const uint8_t blue){
if (indx >= LED_NUM) return;
k_mutex_lock(&ws2812b.gm, K_FOREVER);
/*
set_colour(indx*3*8 + 1*8, rgb_lookup_r[red]);
set_colour(indx*3*8 + 0*8, rgb_lookup_g[green]);
set_colour(indx*3*8 + 2*8, rgb_lookup_b[blue]);
*/
set_colour(indx*3*8 + 1*8, red);
set_colour(indx*3*8 + 0*8, green);
set_colour(indx*3*8 + 2*8, blue);
k_mutex_unlock(&ws2812b.gm);
}
static void ws2812b_set12bitRGB(const struct device *dev, const unsigned int indx, const uint8_t red, const uint8_t green, const uint8_t blue){
}
static void ws2812b_update(const struct device *dev){
k_mutex_lock(&ws2812b.gm, K_FOREVER);
const unsigned int key = irq_lock();
ws2812b.idx = 0;
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_4);
TimerMatchSet(TIMER2_BASE, TIMER_A, 98);
TimerEnable(TIMER2_BASE, TIMER_A);
SysCtlDelay(30);
while(ws2812b.idx < LED_BYTE_NUM) {
}
irq_unlock(key);
k_mutex_unlock(&ws2812b.gm);
}
static const struct led1wire_driver_api ws2812b_driver_api = {
.getAmount = ws2812b_getAmount,
.set8bitRGB = ws2812b_set8bitRGB,
.set12bitRGB = ws2812b_set12bitRGB,
.update = ws2812b_update,
};
static void ws2812b_timer2_A_16_32_isr(void) {
HWREG(TIMER2_BASE + TIMER_O_ICR) = HWREG(TIMER2_BASE + TIMER_O_MIS); //TimerIntClear(TIMER2_BASE, TimerIntStatus(TIMER2_BASE,1));
if(ws2812b.idx >= LED_BYTE_NUM){
TimerDisable(TIMER2_BASE, TIMER_A);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4);
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_4, 0);
return;
}
HWREG(TIMER2_BASE + TIMER_O_TAMATCHR) = ws2812b.ledBytes[ws2812b.idx];
ws2812b.idx++;
}
static int ws2812b_init(const struct device *dev) {
IRQ_DIRECT_CONNECT(23, 0, ws2812b_timer2_A_16_32_isr, INTR_EXTRA_FLAG);
irq_enable(23);
memset(&ws2812b, 0, sizeof(ws2812b));
k_mutex_init(&ws2812b.gm);
const uint32_t Period = 100 ; //800Khz - 1.25uS
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlDelay(3);
GPIOPinConfigure(GPIO_PF4_T2CCP0);
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_4);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
SysCtlDelay(3);
TimerConfigure(TIMER2_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);
TimerLoadSet(TIMER2_BASE, TIMER_A, Period -1);
//This should make so the match register value only updates after a timeout (after the end of the PWM cycle)
HWREG(TIMER2_BASE+TIMER_TAMR_TAMRSU) = 1;
TimerControlEvent(TIMER2_BASE,TIMER_A,TIMER_EVENT_POS_EDGE);
TimerIntEnable(TIMER2_BASE,TIMER_CAPA_EVENT);
ws2812b_update(dev);
return 0;
}
DEVICE_DEFINE(ws2812b_0, "BATTERY_SOCKET_LEDS_0", ws2812b_init,
NULL, NULL, NULL,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&ws2812b_driver_api);