dittoWhat I don't like is that there are those that insist there is no place for .asm in embedded processing, when I can demonstrate conclusively that there are cases where there is no place for C.
dittoWhat I don't like is that there are those that insist there is no place for .asm in embedded processing, when I can demonstrate conclusively that there are cases where there is no place for C.
I agree totally within your restrictive constraints but those constraints are your own and are not general requirements for completion of a specific general programming task.What I don't like is that there are those that insist there is no place for .asm in embedded processing, when I can demonstrate conclusively that there are cases where there is no place for C.
No one writes embedded code for "general programming tasks" -- at least not for commercial products. That's what PCs and mobile devices are for. There is usually a specific end product (or family of products) with specific requirements in mind. And those requirements more often than not include such mundane things as "cost" and "power".I agree totally within your restrictive constraints but those constraints are your own and are not general requirements for completion of a specific general programming task.
That's your option within your market, not a universal truth of micro-controller capability or task requirements.No one writes embedded code for "general programming tasks" -- at least not for commercial products.
We'll leave it at that. To be honest, I forgot what we were arguing about.That's your option within your market, not a universal truth of micro-controller capability or task requirements.
I'm not arguing about anything related to language wars.We'll leave it at that. To be honest, I forgot what we were arguing about.
That was a very bad pop-culture reference. I expect more of you.I'm not arguing about anything related to language wars.
The way I see it, it's quite simple. If Joey expects to optimize to the maximum possible level the way he works personally, but die taking all of his knowledge with him, then he's on the right path. On the other hand, if he plans to either inherit or sell his business to someone else, then that poor fella is going to have the time of his life deciphering his life's work...We'll leave it at that. To be honest, I forgot what we were arguing about.
Now wait a cotton pickin' minute:If Joey expects to optimize to the maximum possible level the way he works personally, but die taking all of his knowledge with him, then he's on the right path. On the other hand, if he plans to either inherit or sell his business to someone else, then that poor fella is going to have the time of his life deciphering his life's work...
Sure, just look on the 'darknets' for experienced exploit writers.Now, the question is: do they still grow experienced .asm programmers? That is the important question.
Not. At. All. ... I did not know about your thoroughly documented code (though I guess I should've inferred that).Or are you suggesting I should hire (or replace myself with) inexperienced .asm programmers?
My libraries are typically fully encapsulated modules that already understand the framework they are being inserted into. I've explained this before (I think in my RN4020 thread).
- Is your library structured in such a way that it would be not just easy to understand, but easy to remember its routines by an experienced programmer?
- Would you consider your library a language on its own? Or does it share similarities in the way its called and invoked with other commercially available libraries?
They're going to bury me at my desk. What else am I going to do? Hang out on AAC?No one lives forever. Is your plan to eventually sell your business to the best bidder? Or you don't know yet what you're going to do?
ledblink 1,1000,25 ;blink LED #1. 1s period, 25ms on-time
ledon 2 ;turn LED #2 solid on
ledoff 3 ;turn LED #3 off
Of course! Buyer beware: I've never used the PIC10 series.I'm about to start learning pic-assembly for the PIC10LF322. Would it bother you if I tagged you every once in a while to ask for your help, Joey? ... I promise I'll do my homework and won't be a pest.
More than you know.It's a matter of satisfaction.
dospi ADS1242_READ_DATA
I know the feeling.More than you know.
Things just feel right when things have been abstracted properly -- and you know when something is missing.
...
The problem is the SPI module requires each device and its commands to be enumerated (by me) in the SPI header (.inc) file. This breaks the abstraction and bugs the hell out of me.
It'd be nice if picasm were extensible. What I need, I think, to solve this problem, is a preprocessor that understands arrays.
/**
* @brief SPI device configuration
*/
typedef struct {
volatile uint32_t *mosi_reg; /**< Output pin mux register address */
volatile uint32_t *miso_reg; /**< MISO pin mux register address */
uint8_t mosi_af; /**< Specify function of output pin */
uint8_t miso_af; /**< Specify input pin for MISO */
gpio_t mosi_pin; /**< GPIO pin for MOSI */
gpio_t miso_pin; /**< GPIO pin for MISO */
} spi_conf_t;
typedef struct {
volatile uint32_t *ipc_regset; /* interrupt controller SET register */
uint32_t iec_mask; /* enables */
uint32_t ifs_mask; /* flags */
uint32_t ipc_mask_p; /* vector pri/sub-pri SFR masks and offsets */
uint32_t ipc_mask_s;
uint32_t ipc_mask_pos_p;
uint32_t ipc_mask_pos_s;
} dma_conf_t;
/** @} */
/**
* @name SPI device configuration
*
* @{
*/
#define SPI_NUMOF (3)
static const spi_conf_t spi_config[] = {
{
.mosi_pin = 0,
.mosi_reg = 0,
.mosi_af = 0,
.miso_pin = 0,
.miso_reg = 0,
.miso_af = 0
}, /* No SPI0 on PIC32, dummy to compile */
{ /*
* SPI 1 (MikBUS 1)
* MOSI -> RD3
* MISO -> RD14
* SCK -> RD1
*/
.mosi_pin = GPIO_PIN(PORT_D, 3),
.mosi_reg = (volatile uint32_t*) & RPD3R,
.mosi_af = OUTPUT_FUNC_SDO1,
.miso_pin = GPIO_PIN(PORT_D, 14),
.miso_reg = (volatile uint32_t*) & SDI1R,
.miso_af = INPUT_PIN_RPD14,
},
{ /*
* SPI 2 (MikBUS 2)
* MOSI -> RG7
* MISO -> RG0
* SCK -> RG6
*/
.mosi_pin = GPIO_PIN(PORT_G, 7),
.mosi_reg = (volatile uint32_t*) & RPG7R,
.mosi_af = OUTPUT_FUNC_SDO2,
.miso_pin = GPIO_PIN(PORT_G, 0),
.miso_reg = (volatile uint32_t*) & SDI2R,
.miso_af = INPUT_PIN_RPG0,
},
{ /*
* SPI 3 (MRF24WN0MA-1/RM100 - wifi module)
* MOSI -> RB9
* MISO -> RB10
* SCK -> RB14
*/
.mosi_pin = GPIO_PIN(PORT_B, 9),
.mosi_reg = (volatile uint32_t*) & RPB9R,
.mosi_af = OUTPUT_FUNC_SDO3,
.miso_pin = GPIO_PIN(PORT_B, 10),
.miso_reg = (volatile uint32_t*) & SDI3R,
.miso_af = INPUT_PIN_RPB10,
},
};
/** @} */
/**
* @name DMA device configuration
*
* @{
*/
#define DMA_NUMOF (8)
/* DMA [0..3] used for SPI ports 1 and 2 */
#define SPI1_DMA_RX 0
#define SPI1_DMA_TX 1
#define SPI2_DMA_RX 2
#define SPI2_DMA_TX 3
static const dma_conf_t dma_config[] = {
{
.iec_mask = _IEC4_DMA0IE_MASK, /* enable */
.ipc_regset = (volatile uint32_t*) & IPC33SET, /* IPC SFR */
.ipc_mask_p = _IPC33_DMA0IP_MASK, /* priority data mask */
.ipc_mask_pos_p = _IPC33_DMA0IP_POSITION, /* priority in SFR */
.ipc_mask_s = _IPC33_DMA0IS_MASK, /* sub-priority */
.ipc_mask_pos_s = _IPC33_DMA0IS_POSITION, /* sub-priority */
},
{
.iec_mask = 0, /* DON'T enable */
.ipc_regset = (volatile uint32_t*) & IPC33SET,
.ipc_mask_p = _IPC33_DMA1IP_MASK,
.ipc_mask_pos_p = _IPC33_DMA1IP_POSITION,
.ipc_mask_s = _IPC33_DMA1IS_MASK,
.ipc_mask_pos_s = _IPC33_DMA1IS_POSITION,
},
{
.iec_mask = _IEC4_DMA0IE_MASK,
.ipc_regset = (volatile uint32_t*) & IPC34SET,
.ipc_mask_p = _IPC34_DMA2IP_MASK,
.ipc_mask_pos_p = _IPC34_DMA2IP_POSITION,
.ipc_mask_s = _IPC34_DMA2IS_MASK,
.ipc_mask_pos_s = _IPC34_DMA2IS_POSITION,
},
{
.iec_mask = 0,
.ipc_regset = (volatile uint32_t*) & IPC34SET,
.ipc_mask_p = _IPC34_DMA3IP_MASK,
.ipc_mask_pos_p = _IPC34_DMA3IP_POSITION,
.ipc_mask_s = _IPC34_DMA3IS_MASK,
.ipc_mask_pos_s = _IPC34_DMA3IS_POSITION,
},
{
.iec_mask = 0,
},
{
.iec_mask = 0,
},
{
.iec_mask = 0,
},
{
.iec_mask = 0,
},
};
/** @} */
void spi_init_pins(spi_t bus)
{
assert(bus != 0 && bus <= SPI_NUMOF);
gpio_init(spi_config[bus].mosi_pin, GPIO_OUT);
gpio_init(spi_config[bus].miso_pin, GPIO_IN);
*(spi_config[bus].mosi_reg) = spi_config[bus].mosi_af;
*(spi_config[bus].miso_reg) = spi_config[bus].miso_af;
}
static void Init_Dma_Chan(uint8_t chan, uint32_t irq_num, volatile unsigned int * SourceDma, volatile unsigned int * DestDma, spi_t bus)
{
assert(chan < DMA_NUMOF);
pic_dma[chan].regs = (volatile uint32_t *)(&DCH0CON + (chan * DMA_REGS_SPACING));
pic_dma[chan].bus = bus;
IEC4CLR = _IEC4_DMA0IE_MASK << chan; /* Disable the DMA chan interrupt. */
IFS4CLR = _IFS4_DMA0IF_MASK << chan; /* Clear the DMA chan interrupt flag. */
DMACONSET = _DMACON_ON_MASK; /* Enable the DMA module. */
DCHxCON(pic_dma[chan]) = 0;
DCHxECON(pic_dma[chan]) = 0;
DCHxINT(pic_dma[chan]) = 0;
DCHxSSA(pic_dma[chan]) = KVA_TO_PA(SourceDma); /* Source start address. */
DCHxDSA(pic_dma[chan]) = KVA_TO_PA(DestDma); /* Destination start address. */
DCHxSSIZ(pic_dma[chan]) = 1; /* default Source bytes. */
DCHxDSIZ(pic_dma[chan]) = 1; /* default Destination bytes. */
DCHxCSIZ(pic_dma[chan]) = 1; /* Bytes to transfer per event. */
DCHxECON(pic_dma[chan]) = irq_num << _DCH0ECON_CHSIRQ_POSITION; /* cell trigger interrupt */
DCHxECONSET(pic_dma[chan]) = _DCH0ECON_SIRQEN_MASK; /* Start cell transfer if an interrupt matching CHSIRQ occurs */
DCHxINTSET(pic_dma[chan]) = _DCH0INT_CHBCIE_MASK; /* enable Channel block transfer complete interrupt. */
/*
* set vector priority and receiver DMA trigger enables for the board hardware configuration
*/
*(dma_config[chan].ipc_regset) = dma_config[chan].ipc_mask_p & (SPIxPRI_SW0 << dma_config[chan].ipc_mask_pos_p);
*(dma_config[chan].ipc_regset) = dma_config[chan].ipc_mask_s & (SPIxSUBPRI_SW0 << dma_config[chan].ipc_mask_pos_s);
IEC4SET = dma_config[chan].iec_mask << chan; /* DMA interrupt enable if needed */
}
static void Release_Dma_Chan(uint8_t chan)
{
assert(chan < DMA_NUMOF);
IEC4CLR = _IEC4_DMA0IE_MASK << chan; /* Disable the DMA interrupt. */
IFS4CLR = _IFS4_DMA0IF_MASK << chan; /* Clear the DMA interrupt flag. */
DCHxCON(pic_dma[chan]) = 0;
DCHxECON(pic_dma[chan]) = 0;
DCHxINT(pic_dma[chan]) = 0;
}
I know what you are saying, but you kinda missed my point.In C, the structure, pointer, array and other standard abstractions can be used to create functions that can easily dynamically configure devices or command sequences with the same code on just about any processor that supports a standard GCC like compiler.
So you're saying you've built yourself your own personal "middle-level" language based on a low-level library?Then I can write macros to build the structures for me at assembly time, abstracted away from the actual code.